﻿using System;
using System.Globalization;
using System.Net;
using System.Threading;
using System.Threading.RateLimiting;
using System.Threading.Tasks;
using Common;
using Common.DataModels;
using Extensions.Services.RateLimit.Config;
using Extensions.Services.RateLimit.Policys;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.DependencyInjection;
using Nest;

namespace Extensions.Services.RateLimit;

/// <summary>
/// 限流 .net core 默认的限流中间件
/// </summary>
public static class AddRateLimite
{
    public static IServiceCollection AddRateLimitSetup(this IServiceCollection services)
    {
        ArgumentNullException.ThrowIfNull(services);
        var config = Appsettings.app<RateLimitConfig>("RateLimit");
        ArgumentNullException.ThrowIfNull(config);
        if (!config.Enable)
        {
            Console.WriteLine("限流配置为不启动");
            return services;
        }
        services.AddRateLimiter(options =>
        {
            // 并发 限流策略
            options.AddPolicy<IPAddress, ConcurrencyLimiterPolicy>("Concurrency");
            // 固定窗口限流
            options.AddPolicy<IPAddress, FixedWindowLimiterPolicy>("Fixed");
            // 滑动窗口限流
            options.AddPolicy<IPAddress, SlidingWindowLimiterPolicy>("Sliding");
            // 令牌桶限流
            options.AddPolicy<IPAddress, TokenBucketLimiterPolicy>("Token");
            // 全局的过滤器

            // 全局过滤器的令牌桶算法
            //options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, IPAddress>(context =>
            //{
            //    // 获取远程地址
            //    var remoteIpAddress = context.Connection.RemoteIpAddress;
            //    if (!IPAddress.IsLoopback(remoteIpAddress))
            //    {
            //        return RateLimitPartition.GetTokenBucketLimiter(remoteIpAddress!, _ => new TokenBucketRateLimiterOptions()
            //        {
            //            TokenLimit = 20,
            //            QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
            //            QueueLimit = 2,
            //            ReplenishmentPeriod = TimeSpan.FromSeconds(2),
            //            TokensPerPeriod = 4,
            //            AutoReplenishment = false
            //        });
            //    }
            //    // 回环的地址不做限流
            //    return RateLimitPartition.GetNoLimiter(IPAddress.Loopback);
            //});
        });

        return services;
    }
}